import { BrowserWindow, dialog, ipcMain } from 'electron'
import { mainWindow } from '.'
import { CallerSourceType, CanvasMethod } from './store/canvas/canvasType'
import CanvasData from './store/canvas/canvas'
import { promises as fs } from 'fs'
import canvas from './store/canvas/canvas'
import { getChildWindowsId, openChildWindow, setChildWindowsId } from './store/winId.ts/windowsId'
import { sendMsgToRender } from './store/message/message'
import SvgData from './store/svgData/svgData'
import { SvgDataMethod } from './store/svgData/svgDataType'
import { RandomFunMethod } from './store/randomFun/randomFunType'
import RandomFun from './store/randomFun/randomFun'
import { simController } from './simEngine/simulation/SimController'
import { TrafficNetMethod } from './store/trafficNetwork/trafficNetType'
import TrafficNetwork from './store/trafficNetwork/trafficNetwork'

export const monitorEvent = (): void => {
  //========================================= 关于窗口事件 ================================================================================================

  //监听标题栏右侧三个按钮
  ipcMain.on('winSize', (e, data) => {
    if (data === 'hide') {
      //最小化窗口
      mainWindow.minimize()
    } else if (data === 'min') {
      //取消最大化
      mainWindow.unmaximize()
    } else if (data === 'max') {
      //最大化
      mainWindow.maximize()
    } else if (data === 'close') {
      //关闭程序
      mainWindow.close()
    }
  })

  //打开一个子窗口
  ipcMain.on('openChild', (e, data) => {
    //判断是否已经打开过该窗口
    const winId = getChildWindowsId(data.key)
    if (winId !== null) {
      sendMsgToRender('window', data.title + '窗口已存在')
      //窗口已经存在,则发送一些初始数据
      const childWindow = BrowserWindow.fromId(winId)
      if (childWindow === null) {
        sendMsgToRender('window', '发生异常,窗口不存在', 'warning')
        return
      }

      childWindow.webContents.send('initData', {
        id: childWindow.id,
        key: data.key,
        title: data.title,
        data: data?.data
      })

      //将窗口显示出来
      childWindow.show()
    } else {
      openChildWindow(data)
    }
  })

  //监听子窗口关闭事件
  ipcMain.on('childWinSize', (e, data) => {
    const winId = data.id
    //找到那个子窗口
    const childWindow = BrowserWindow.fromId(winId)
    if (childWindow === null) {
      sendMsgToRender('window', '发生异常,窗口不存在', 'warning')
      return
    }
    if (data.type === 'hide') {
      //最小化窗口
      childWindow.minimize()
    } else if (data.type === 'min') {
      //取消最大化
      childWindow.unmaximize()
    } else if (data.type === 'max') {
      //最大化
      childWindow.maximize()
    } else if (data.type === 'close') {
      //关闭程序
      childWindow.close()
      setChildWindowsId(null, data.key)
    }
  })

  //========================================= 画布-节点-仿真 ================================================================================================

  // 监听画布数据处理事件
  ipcMain.on(
    'handleCanvasData',
    (
      e,
      methodName: CanvasMethod,
      callerSource: CallerSourceType, // 新增调用来源
      isBroadcast: boolean, // 是否广播
      args: Parameters<(typeof CanvasData)[CanvasMethod]>
    ) => {
      const result = CanvasData.executeMethod(methodName, callerSource, isBroadcast, true, ...args)
      e.returnValue = result
    }
  )

  //仿真状态切换
  ipcMain.on('simulationStatus', (e, data) => {
    simController.setStatus(data)
  })

  //仿真速度切换
  ipcMain.on('simulationSpeed', (e, data) => {
    simController.changeSpeed(data)
  })

  //获取节点icon
  ipcMain.handle(
    'nodeIcon',
    (e, methodName: SvgDataMethod, args: Parameters<(typeof SvgData)[SvgDataMethod]>) => {
      const result = SvgData.executeMethod(methodName, ...args)
      return result
    }
  )

  //处理交通网络
  ipcMain.handle(
    'handleTrafficNetwork',
    (
      e,
      methodName: TrafficNetMethod,
      args: Parameters<(typeof TrafficNetwork)[TrafficNetMethod]>
    ) => {
      const result = TrafficNetwork.executeMethod(methodName, ...args)
      return result
    }
  )

  //获取随机函数
  ipcMain.handle(
    'randomFun',
    (e, methodName: RandomFunMethod, args: Parameters<(typeof RandomFun)[RandomFunMethod]>) => {
      const result = RandomFun.executeMethod(methodName, ...args)
      return result
    }
  )

  //========================================= 属性栏 ================================================================================================

  // 监听打开属性栏窗口的事件, 拿到数据不做处理，直接发给属性栏窗口
  ipcMain.on('openAttributeWindow', (e, data) => {
    mainWindow.webContents.send('attributeWindowData', data)
  })

  //========================================= 资源栏 ================================================================================================

  //画布的节点名字被修改，通知资源栏
  ipcMain.on('changeNodeNameToResource', (e, data) => {
    mainWindow.webContents.send('resourceChangeNodeName', data)
  })

  //========================================= 文件 ================================================================================================

  //保存画布文件
  ipcMain.on('saveCanvasFile', async (e) => {
    const options = {
      title: '保存文件',
      defaultPath: `canvas.json`,
      buttonLabel: '保存',
      filters: [{ name: 'JSON Files', extensions: ['json'] }]
    }
    const result = await dialog.showSaveDialog(options)
    const filePath = result.filePath
    const canvasData = CanvasData.getCanvas()

    try {
      await fs.writeFile(filePath, JSON.stringify(canvasData, null, 2), 'utf-8')
    } catch (err) {
      console.log(err)
    }
  })

  //打开画布文件
  ipcMain.on('openCanvasFile', async (e) => {
    const result = await dialog.showOpenDialog({
      properties: ['openFile'],
      filters: [{ name: 'JSON Files', extensions: ['json'] }]
    })
    const filePath = result.filePaths[0]
    try {
      const jsonData = await fs.readFile(filePath, 'utf-8')
      canvas.executeMethod('clearCanvas', 'mainProcess', true)
      canvas.executeMethod('setCanvas', 'mainProcess', true, true, JSON.parse(jsonData))
    } catch (err) {
      console.log(err)
    }
  })
}
